#!/usr/bin/python3

import loguru
import socket
import serial
import threading
import codecs


def bytesPrettyPrint(b: bytes):
    """直观打印数据包"""
    if len(b) == 0:
        return "None Pack"
    st = codecs.encode(b, "hex").decode("utf-8").upper()
    it = iter(st)
    result_str = " ".join(a + b for a, b in zip(it, it))
    return result_str


def sent_to_serial(sock, ser, logger):
    global sock_dead_flag
    while True:
        try:
            data = sock.recv(1024)
            logger.info("send to serial | {}".format(bytesPrettyPrint(data)))
            if data is not None and len(data) > 0:
                ser.write(data)
            else:
                logger.exception("sent_to_serial sock.recv data | {}".format(data))
                sock_dead_flag = True
                break
        except Exception:
            logger.exception("sent_to_serial failed exit")
            break


def recv_from_serial(sock, ser, logger):
    global sock_dead_flag
    while True:
        try:
            if sock_dead_flag is True:
                return
            else:
                data = ser.read(1024)
                if data is not None and len(data) > 0:
                    logger.info("recv from serial | {}".format(bytesPrettyPrint(data)))
                    sock.send(data)
        except Exception:
            logger.exception("recv_from_serial failed exit")
            break


if __name__ == '__main__':
    # 日志对象
    logger = loguru.logger
    # 掉线标志
    sock_dead_flag = False
    # 串口
    ser = serial.Serial()
    ser.port = "COM11"
    ser.timeout = 1
    ser.open()
    # 服务端配置 暴露给公网
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(("127.0.0.1", 6000))
    server.listen(0)
    while True:
        sock, client_address = server.accept()
        logger.info("开始处理入站数据")
        sock_dead_flag = False
        t1 = threading.Thread(target=sent_to_serial, args=(sock, ser, logger))
        t1.start()
        t2 = threading.Thread(target=recv_from_serial, args=(sock, ser, logger))
        t2.start()
        t1.join()
        t2.join()
        logger.info("处理入站数据结束")
